package com.google.gson.reflect;

import cn.hutool.core.util.TypeUtil;
import com.google.gson.internal.$Gson$Types;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class TypeToken<T> {

    private final Class<? super T> rawType;
    private final Type type;
    private final int hashCode;

    protected TypeToken(Type type) {
        this.type = type;
        this.rawType = (Class<? super T>) $Gson$Types.getRawType(type);
        this.hashCode = type.hashCode();
    }

    protected TypeToken() {
        this.type = getTypeTokenTypeArgument();
        this.rawType = (Class<? super T>) $Gson$Types.getRawType(type);
        this.hashCode = type.hashCode();
    }

    /**
     * Gets type literal for the given {@code Type} instance.
     */
    public static <T> TypeToken<T> get(Type type) {
        return new TypeToken<>(type);
    }

    public Type getType() {
        return type;
    }

    public Class<?> getRawType() {
        return rawType;
    }

    public int getHashCode() {
        return hashCode;
    }


    /**
     * Verifies that {@code this} is an instance of a direct subclass of TypeToken and
     * returns the type argument for {@code T} in {@link $Gson$Types#canonicalize
     * canonical form}.
     */
    private Type getTypeTokenTypeArgument() {
        Type superclass = getClass().getGenericSuperclass();
        if (superclass instanceof ParameterizedType) {
            ParameterizedType parameterized = (ParameterizedType) superclass;
            if (parameterized.getRawType() == TypeToken.class) {
                return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
            }
        }

        throw new IllegalStateException("Must only create direct subclasses of TypeToken");
    }
}
